/* Author: David McCoy dave.mccoy@cospandesign.com
 *
 *     This file is part of DLCM\SubServ.
 *
 *  DLCM\SubServ is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  DLCM\SubServ is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with DLCM\SubServ.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 * NetworkInterfacePanel.java
 *
 * Used to read the host machines network interfaces
 *
 * Created on Mar 26, 2010, 12:25:25 AM
 */

package com.cospandesign.gui.providers;

import java.awt.Color;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;


/**
 *
 * @author cospan
 */
public class NetworkInterfacePanel extends javax.swing.JPanel{

    DefaultMutableTreeNode RootNode;
    String IPString;
    boolean UDPFlag = false;
    private static final String UDP_TREE_NAME = "UDP IP Address";
    private static final String UDP_IP_ADDRESS = "239.255.76.67";
//    Mutex NetworkLoaderMutex;
    volatile boolean LoadingNetwork = false;

    /** Creates new form NetworkInterfacePanel */
    public NetworkInterfacePanel() throws SocketException {
        initComponents();

 //       NetworkLoaderMutex = new Mutex();

        //ReloadTree();

    }
    

    // <editor-fold defaultstate="collapsed" desc="Pulic Methods">
    public synchronized void ReloadTree() throws SocketException {

        if (LoadingNetwork){
            return;
        }

        Thread t = new Thread (new NetworkLoader());
        t.start();
    }

    public void setUDPSupport(boolean flag) {
        UDPFlag = flag;
    }

    public String getIPString() {
        return IPString;
    }// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Network Background Loader">
    public class NetworkLoader implements Runnable {

        public void run() {
            //Setup RootNode

            String statusString = new String("Searching for Network Interfaces...");
            Integer count = 0;

            //NetworkLoaderMutex.lock();
            LoadingNetwork = true;

            TitledBorder tb = (TitledBorder) getBorder();
            synchronized (tb){
                tb.setTitle(statusString);
                tb.setTitleColor(Color.BLUE);
            }
            RootNode = (DefaultMutableTreeNode) NetworkInterfaceTree.getModel().getRoot();
            TreeModel tm = NetworkInterfaceTree.getModel();
            RootNode.removeAllChildren();
            DefaultMutableTreeNode tn = new DefaultMutableTreeNode("Enter Custom IP");
            RootNode.add(tn);
            if (UDPFlag) {
                tn = new DefaultMutableTreeNode(UDP_TREE_NAME);
                RootNode.add(tn);
            }

            IPString = new String("127.0.0.1");


            Enumeration interfaces = null;
            try {
                interfaces = NetworkInterface.getNetworkInterfaces();
            } catch (SocketException ex) {
                Logger.getLogger(NetworkInterfacePanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (!interfaces.hasMoreElements()) {
                return;
            }
            //Traverse the interfaces, and add them to the tree
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) interfaces.nextElement();
                niObject no = new niObject(ni);
                try {
                    if (!ni.isUp()) {
                        continue;
                    }
                } catch (SocketException ex) {
                    Logger.getLogger(NetworkInterfacePanel.class.getName()).log(Level.SEVERE, null, ex);
                }

                count++;
                statusString = "Found " + count.toString() + " Interface(s)";
                tb.setTitle(statusString);
                repaint();
                DefaultMutableTreeNode mtn = new DefaultMutableTreeNode(no);
                //mtn.setUserObject(ni);
                RootNode.add(mtn);

                //go through all the sup network interfaces
                if (!ni.getSubInterfaces().hasMoreElements()) {
                    continue;
                }
                Enumeration subInterfaces = ni.getSubInterfaces();
                //go through all the subnodes
                while (subInterfaces.hasMoreElements()) {
                    NetworkInterface sni = (NetworkInterface) subInterfaces.nextElement();
                    niObject sno = new niObject(sni);
                    DefaultMutableTreeNode smtn = new DefaultMutableTreeNode(sno);
                    //smtn.setUserObject(sni);
                    mtn.add(smtn);
                }

            }
            tb.setTitle("Network Interfaces");
            tb.setTitleColor(Color.BLACK);
            NetworkInterfaceTree.setModel(new DefaultTreeModel(RootNode));
            repaint();

            //NetworkLoaderMutex.unlock();
            LoadingNetwork = false;
        }
    }// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Workaround Class">
    public class niObject {

        public NetworkInterface ni;

        @Override
        public String toString() {
            return ni.getDisplayName();
        }

        public niObject(NetworkInterface n) {
            ni = n;
        }
    }

    // </editor-fold>

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        NetworkInterfaceTree = new javax.swing.JTree();
        IP1TextBox = new javax.swing.JFormattedTextField();
        jLabel3 = new javax.swing.JLabel();
        IP2TextBox = new javax.swing.JFormattedTextField();
        jLabel4 = new javax.swing.JLabel();
        IP3TextBox = new javax.swing.JFormattedTextField();
        jLabel5 = new javax.swing.JLabel();
        IP4TextBox = new javax.swing.JFormattedTextField();
        CustomIPButton = new javax.swing.JButton();

        setBorder(javax.swing.BorderFactory.createTitledBorder("IP Address"));

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Network Interfaces");
        javax.swing.tree.DefaultMutableTreeNode treeNode2 = new javax.swing.tree.DefaultMutableTreeNode("Enter Custom IP");
        treeNode1.add(treeNode2);
        NetworkInterfaceTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        NetworkInterfaceTree.setName("NetworkInterfaceTree"); // NOI18N
        NetworkInterfaceTree.setRootVisible(false);
        NetworkInterfaceTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                NetworkInterfaceTreeValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(NetworkInterfaceTree);

        IP1TextBox.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        IP1TextBox.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        IP1TextBox.setText("127");
        IP1TextBox.setName("IP1TextBox"); // NOI18N

        jLabel3.setText(" . ");
        jLabel3.setName("jLabel3"); // NOI18N

        IP2TextBox.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        IP2TextBox.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        IP2TextBox.setText("0");
        IP2TextBox.setName("IP2TextBox"); // NOI18N

        jLabel4.setText(" . ");
        jLabel4.setName("jLabel4"); // NOI18N

        IP3TextBox.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        IP3TextBox.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        IP3TextBox.setText("0");
        IP3TextBox.setName("IP3TextBox"); // NOI18N

        jLabel5.setText(" . ");
        jLabel5.setName("jLabel5"); // NOI18N

        IP4TextBox.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        IP4TextBox.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        IP4TextBox.setText("1");
        IP4TextBox.setName("IP4TextBox"); // NOI18N

        CustomIPButton.setText("Set Custom IP");
        CustomIPButton.setEnabled(false);
        CustomIPButton.setName("CustomIPButton"); // NOI18N
        CustomIPButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CustomIPButtonActionPerformed(evt);
            }
        });
        CustomIPButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                CustomIPButtonFocusLost(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(CustomIPButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addComponent(IP1TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(3, 3, 3)
                        .addComponent(jLabel3)
                        .addGap(5, 5, 5)
                        .addComponent(IP2TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(5, 5, 5)
                        .addComponent(jLabel4)
                        .addGap(3, 3, 3)
                        .addComponent(IP3TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(5, 5, 5)
                        .addComponent(jLabel5)
                        .addGap(3, 3, 3)
                        .addComponent(IP4TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 178, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(IP1TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(IP2TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(IP3TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(IP4TextBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jLabel4)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(CustomIPButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void NetworkInterfaceTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_NetworkInterfaceTreeValueChanged
        Object o = ((DefaultMutableTreeNode)evt.getPath().getLastPathComponent()).getUserObject();
        if (o.getClass().equals(String.class)){
            String ipName = (String)o;
            //we are using a custom IP
            if (ipName.equals(UDP_TREE_NAME)){
                String ip = UDP_IP_ADDRESS;

                String [] ips = ip.split("\\.");
                IP1TextBox.setText(ips[0]);
                IP2TextBox.setText(ips[1]);
                IP3TextBox.setText(ips[2]);
                IP4TextBox.setText(ips[3]);

                IPString = ip;
                return;

            }
            CustomIPButton.setEnabled(true);
        }
        else{

            CustomIPButton.setEnabled(false);
            NetworkInterface ni = ((niObject) o).ni;

            Enumeration eni = ni.getInetAddresses();

            if (!eni.hasMoreElements()){
                return;
            }

            InetAddress addr = null;
            while (eni.hasMoreElements()){
                addr = (InetAddress) eni.nextElement();
                if (addr.getClass().equals(Inet4Address.class)){
                    break;
                }
            }


            String ip = addr.getHostAddress();

            String [] ips = ip.split("\\.");
            IP1TextBox.setText(ips[0]);
            IP2TextBox.setText(ips[1]);
            IP3TextBox.setText(ips[2]);
            IP4TextBox.setText(ips[3]);

            IPString = ip;

        }
    }//GEN-LAST:event_NetworkInterfaceTreeValueChanged

    private void CustomIPButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CustomIPButtonActionPerformed

        Integer val = null;
        boolean success = true;

        val = Integer.parseInt(IP1TextBox.getText());
        if ((val > 255) || (val < 0)){
            IP1TextBox.setBackground(Color.red);
            success = false;
        }
        val = Integer.parseInt(IP2TextBox.getText());
        if ((val > 255) || (val < 0)){
            IP2TextBox.setBackground(Color.red);
            success = false;
        }
        val = Integer.parseInt(IP3TextBox.getText());
        if ((val > 255) || (val < 0)){
            IP3TextBox.setBackground(Color.red);
            success = false;
        }
        val = Integer.parseInt(IP4TextBox.getText());
        if ((val > 255) || (val < 0)){
            IP4TextBox.setBackground(Color.red);
            success = false;
        }
        if (!success){
            return;
        }

        //Values are good, generate an IPString
        IPString = IP1TextBox.getText() + "." + IP2TextBox.getText() + "." + IP3TextBox.getText() + "." + IP4TextBox.getText();

    }//GEN-LAST:event_CustomIPButtonActionPerformed

    private void CustomIPButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_CustomIPButtonFocusLost
        IP1TextBox.setBackground(Color.white);
        IP2TextBox.setBackground(Color.white);
        IP3TextBox.setBackground(Color.white);
        IP4TextBox.setBackground(Color.white);
    }//GEN-LAST:event_CustomIPButtonFocusLost


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton CustomIPButton;
    public javax.swing.JFormattedTextField IP1TextBox;
    public javax.swing.JFormattedTextField IP2TextBox;
    public javax.swing.JFormattedTextField IP3TextBox;
    public javax.swing.JFormattedTextField IP4TextBox;
    private javax.swing.JTree NetworkInterfaceTree;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables



}
